﻿// Decompiled with JetBrains decompiler
// Type: TaleWorlds.MountAndBlade.View.MissionViews.MissionFormationTargetSelectionHandler
// Assembly: TaleWorlds.MountAndBlade.View, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: 61152EB8-513B-4D4A-8AC0-0D1465C6CF6C
// Assembly location: D:\steam\steamapps\common\Mount & Blade II Bannerlord\Modules\Native\bin\Win64_Shipping_Client\TaleWorlds.MountAndBlade.View.dll

using System;
using System.Collections.Generic;
using System.Diagnostics;
using TaleWorlds.Engine;
using TaleWorlds.Library;

#nullable disable
namespace TaleWorlds.MountAndBlade.View.MissionViews
{
  public class MissionFormationTargetSelectionHandler : MissionView
  {
    public const float MaxDistanceForFocusCheck = 1000f;
    public const float MinDistanceForFocusCheck = 10f;
    public readonly float MaxDistanceToCenterForFocus = (float) (70.0 * ((double) Screen.RealScreenResolutionHeight / 1080.0));
    private readonly List<(Formation, float)> _distanceCache;
    private readonly MBList<Formation> _focusedFormationCache;
    private Vec2 _centerOfScreen = new Vec2(Screen.RealScreenResolutionWidth / 2f, Screen.RealScreenResolutionHeight / 2f);

    public event Action<MBReadOnlyList<Formation>> OnFormationFocused;

    private Camera ActiveCamera
    {
      get => this.MissionScreen.CustomCamera ?? this.MissionScreen.CombatCamera;
    }

    public MissionFormationTargetSelectionHandler()
    {
      this._distanceCache = new List<(Formation, float)>();
      this._focusedFormationCache = new MBList<Formation>();
    }

    public override void OnPreDisplayMissionTick(float dt)
    {
      base.OnPreDisplayMissionTick(dt);
      this._distanceCache.Clear();
      this._focusedFormationCache.Clear();
      if (this.Mission?.Teams == null)
        return;
      Vec3 position = this.ActiveCamera.Position;
      this._centerOfScreen.x = Screen.RealScreenResolutionWidth / 2f;
      this._centerOfScreen.y = Screen.RealScreenResolutionHeight / 2f;
      for (int index1 = 0; index1 < this.Mission.Teams.Count; ++index1)
      {
        Team team = this.Mission.Teams[index1];
        if (!team.IsPlayerAlly)
        {
          for (int index2 = 0; index2 < team.FormationsIncludingEmpty.Count; ++index2)
          {
            Formation formation = team.FormationsIncludingEmpty[index2];
            if (formation.CountOfUnits > 0)
            {
              float distanceToCenter = this.GetFormationDistanceToCenter(formation, position);
              this._distanceCache.Add((formation, distanceToCenter));
            }
          }
        }
      }
      if (this._distanceCache.Count == 0)
      {
        Action<MBReadOnlyList<Formation>> formationFocused = this.OnFormationFocused;
        if (formationFocused == null)
          return;
        formationFocused((MBReadOnlyList<Formation>) null);
      }
      else
      {
        Formation formation = (Formation) null;
        float num = this.MaxDistanceToCenterForFocus;
        for (int index = 0; index < this._distanceCache.Count; ++index)
        {
          (Formation, float) tuple = this._distanceCache[index];
          if ((double) tuple.Item2 == 0.0)
            this._focusedFormationCache.Add(tuple.Item1);
          else if ((double) tuple.Item2 < (double) num)
          {
            num = tuple.Item2;
            formation = tuple.Item1;
          }
        }
        if (formation != null)
          this._focusedFormationCache.Add(formation);
        Action<MBReadOnlyList<Formation>> formationFocused = this.OnFormationFocused;
        if (formationFocused == null)
          return;
        formationFocused((MBReadOnlyList<Formation>) this._focusedFormationCache);
      }
    }

    private float GetFormationDistanceToCenter(Formation formation, Vec3 cameraPosition)
    {
      WorldPosition medianPosition = formation.QuerySystem.MedianPosition;
      medianPosition.SetVec2(formation.QuerySystem.AveragePosition);
      float num = formation.QuerySystem.AveragePosition.Distance(cameraPosition.AsVec2);
      if ((double) num >= 1000.0)
        return (float) int.MaxValue;
      if ((double) num <= 10.0)
        return 0.0f;
      float screenX = 0.0f;
      float screenY = 0.0f;
      float w = 0.0f;
      double insideUsableArea = (double) MBWindowManager.WorldToScreenInsideUsableArea(this.ActiveCamera, medianPosition.GetGroundVec3() + new Vec3(z: 3f), ref screenX, ref screenY, ref w);
      return (double) w <= 0.0 ? (float) int.MaxValue : new Vec2(screenX, screenY).Distance(this._centerOfScreen);
    }

    public override void OnRemoveBehavior()
    {
      this._distanceCache.Clear();
      this._focusedFormationCache.Clear();
      this.OnFormationFocused = (Action<MBReadOnlyList<Formation>>) null;
      base.OnRemoveBehavior();
    }

    [Conditional("DEBUG")]
    public void TickDebug()
    {
    }
  }
}
